package com.sim.core.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HttpClientUtil {
	private static Logger logger = LoggerFactory.getLogger(ImKit.class);
	private static PoolingHttpClientConnectionManager connMgr;
	private static RequestConfig requestConfig;

	public static void init() {
		// 设置连接池
		connMgr = new PoolingHttpClientConnectionManager();
		// 设置连接池大小
		connMgr.setMaxTotal(500);
		connMgr.setDefaultMaxPerRoute(connMgr.getMaxTotal());
		RequestConfig.Builder configBuilder = RequestConfig.custom();
		// 设置连接超时
		configBuilder.setConnectTimeout(60000);
		// 设置读取超时
		configBuilder.setSocketTimeout(60000);
		// 设置从连接池获取连接实例的超时
		configBuilder.setConnectionRequestTimeout(10000);
		// 在提交请求之前 测试连接是否可用
		connMgr.setValidateAfterInactivity(10000);
		requestConfig = configBuilder.build();
		logger.info("[HttpclientApiInvoker] invoke init success and finish!!!");
	}

	public static String get(String url){
		return get(url,null);
	}

	/**
	 * 请求get
	 * @param url
	 * @param param
	 * @return
	 */
	public static String get(String url, Map<String, String> param) {
		return get(url,param,null);
	}

	public static String get(String url, Map<String, String> param, String token) {
		String result = "";
		CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()).setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build();
		HttpGet httpGet = new HttpGet(url);
		CloseableHttpResponse response = null;
		HttpEntity entity;
		try {
			httpGet.addHeader(HTTP.USER_AGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			httpGet.setConfig(requestConfig);
			httpGet.setHeader(HTTP.CONN_KEEP_ALIVE, "true");
			if(!StringUtils.isEmpty(token)) {
				httpGet.addHeader("Authorization", "Bearer " + token); //认证token
			}
			String urlString  = "";
			if(null != param && !param.isEmpty()){
				urlString  = "?" + buildMapString(param);
			}
			httpGet.setURI(URI.create(url + urlString));
			logger.info("[HttpclientApiInvoker] req get, url: {}",(url + urlString));
			response = httpClient.execute(httpGet);
			int statusCode = response.getStatusLine().getStatusCode();
			logger.info("[HttpclientApiInvoker] invoking, response status: {}",statusCode);
			if (statusCode != HttpStatus.SC_OK) {
				logger.error("[HttpclientApiInvoker] invoke failed, response status: {}",statusCode);
				return result;
			}
			entity = response.getEntity();
			if (entity == null) {
				logger.error("[HttpclientApiInvoker] invoke failed, response output is null!");
				return result;
			}
			result = EntityUtils.toString(entity, "utf-8");
			return result;
		} catch (Exception e) {
			logger.error("[HttpclientApiInvoker] invoke throw exception, details: {}", e);
		} finally {
			if (response != null) {
				try {
					EntityUtils.consume(response.getEntity());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}

	/**
	 * @param url
	 * @param param
	 * @return
	 */
	public static String post(String url, Map<String, String> param) {
		String result = "";
		CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()).setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build();
		HttpPost httpPost = new HttpPost(url);
		CloseableHttpResponse response = null;
		HttpEntity entity;
		try {
			httpPost.setConfig(requestConfig);
			httpPost.setHeader(HTTP.CONN_KEEP_ALIVE, "true");
			//建立一个NameValuePair数组，用于存储欲传送的参数
			List<NameValuePair> params = new ArrayList<NameValuePair>();
			for (Map.Entry<String, String> entry : param.entrySet()) {
				params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
			}
			UrlEncodedFormEntity se = new UrlEncodedFormEntity(params, Charset.forName("UTF-8"));
			//添加参数
			httpPost.setEntity(se);
			response = httpClient.execute(httpPost);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode != HttpStatus.SC_OK) {
				logger.error("[HttpclientApiInvoker] invoke failed, response status: {}" ,statusCode);
				return result;
			}
			entity = response.getEntity();
			if (entity == null) {
				logger.error("[HttpclientApiInvoker] invoke failed, response output is null!");
				return result;
			}
			result = EntityUtils.toString(entity, "utf-8");
			return result;
		} catch (Exception e) {
			logger.error("[HttpclientApiInvoker] invoke throw exception, details: {}", e);
		} finally {
			if (response != null) {
				try {
					EntityUtils.consume(response.getEntity());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}

	public static String post(String url, Map<String, Object> param, String token) throws IOException {
		CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()).setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build();
		HttpPost httpPost = new HttpPost(url);
		CloseableHttpResponse response = null;
		HttpEntity entity;

		try {
			httpPost.setConfig(requestConfig);
			// 设置通用的请求属性
			httpPost.addHeader(HTTP.USER_AGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			httpPost.addHeader("accept", "*/*");
			if(!StringUtils.isEmpty(token)) {
				httpPost.addHeader("Authorization", "Bearer " + token); //认证token
			}
			httpPost.addHeader("Content-Type", "application/json;charset=utf-8");
			httpPost.setHeader(HTTP.CONN_KEEP_ALIVE, "true");

			if(param != null && param.keySet().size() > 0){
				String json = JSONObject.toJSONString(param);
				StringEntity se = new StringEntity(json , "UTF-8");
				//添加参数
				httpPost.setEntity(se);
			}

			response = httpClient.execute(httpPost);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode != HttpStatus.SC_OK) {
				logger.error("[HttpclientApiInvoker] invoke failed, response status: {}",statusCode);
				return null;
			}
			entity = response.getEntity();
			if (entity == null) {
				logger.error("[HttpclientApiInvoker] invoke failed, response output is null!");
				return null;
			}
			String result = EntityUtils.toString(entity, "utf-8");
			return result;
		} catch (Exception e) {
			logger.error("[HttpclientApiInvoker] invoke throw exception, details:{} ", e);
			e.printStackTrace();
		} finally {
			if (response != null) {
				EntityUtils.consume(response.getEntity());
			}
		}
		return null;
	}

	public static String buildMapString(Map<String, String> map) {
		StringBuffer sb = new StringBuffer();
		if (null != map && !map.isEmpty()) {
			for (String key : map.keySet()) {
				sb.append(key + "=");
				if (StringUtils.isEmpty(map.get(key))) {
					sb.append("&");
				} else {
					String value = map.get(key);
					try {
						value = URLEncoder.encode(value, "UTF-8");
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}
					sb.append(value + "&");
				}
			}
		}
		return sb.toString();
	}

	private static SSLConnectionSocketFactory createSSLConnSocketFactory() {
		SSLConnectionSocketFactory sslsf = null;
		try {
			SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {

				public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
					return true;
				}
			}).build();
			sslsf = new SSLConnectionSocketFactory(sslContext, (arg0, arg1) -> true);
		} catch (GeneralSecurityException e) {
			logger.error(e.getMessage(), e);
		}
		return sslsf;
	}

	public static void main(String[] args) {
		try{
			String url = "http://localhost:8110/user/login/currentUserInfo";
			String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiIxODAwNzQ3MDI1MiIsInNjb3BlIjpbIioiXSwibmV3VXNlciI6ZmFsc2UsImV4cCI6MTYyODkzNjYxNCwiYXV0aG9yaXRpZXMiOlsiVVNFUl9ST0xFIl0sImp0aSI6ImUwZTJlZDUxLTQzYTgtNGE3Mi1iYmEwLWM5YzUzYzQ5Njc5NSIsImNsaWVudF9pZCI6ImZ6Y2xvdWQtY2xpZW50LWJ1YyIsInRpbWVzdGFtcCI6MTYyNjM0NDYxNDAyOX0.QYdn-S5ej4pCl2H5zx6aBBVunNJm0E995cqgmU0IF3k";
			String response = post(url,null,token);
			System.out.println(response);
		}
		catch (Exception e){
			e.printStackTrace();
		}
	}
}